import base64
import os
import subprocess

import requests

from flask import request, redirect, url_for, session, jsonify, Response
from flask_mysqldb import MySQL
from wtforms import Form, StringField, PasswordField, validators
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from flask import Flask, render_template
from flask_caching import Cache
import warnings
import datetime
import face_compare_python3_demo

warnings.filterwarnings('ignore')

app = Flask(__name__,static_url_path='/static')
#数据加密功能
app.secret_key = '2440814347'

# 配置MySQL
app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'root'
app.config['MYSQL_DB'] = 'library'
app.config['MYSQL_CURSORCLASS'] = 'DictCursor'


mysql = MySQL(app)
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'


# 用户类，用于处理登录和注销
class User(UserMixin):
    def __init__(self, id, username, is_admin):
        self.id = id
        self.username = username
        self.is_admin = is_admin

#保留浏览器缓存图片
#配置缓存
cache= Cache(app, config={'CACHE_TYPE': 'simple'})
# 将静态文件的缓存超时设置为一天（以秒为单位）
ONE_DAY = 24 * 60 * 60

#监测响应
@app.after_request
def add_header(response):
    print(response)
    if response.status_code == 200 and response.mimetype.startswith('image/'):
        response.cache_control.public = True
        response.cache_control.max_age = ONE_DAY
    return response

# 从数据库加载用户
@login_manager.user_loader
def load_user(user_id):
    cur = mysql.connection.cursor()
    cur.execute('SELECT * FROM users WHERE id = %s', [user_id])
    user = cur.fetchone()
    cur.close()
    if user:
        return User(user_id, user['username'], is_admin=False)
    else:
        cur = mysql.connection.cursor()
        cur.execute('SELECT * FROM administrator WHERE id = %s', [user_id])
        user = cur.fetchone()
        cur.close()
        return User(user_id, user['username'], is_admin=True)


# 表单类
class BookForm(Form):
    # 书名
    title = StringField('Title', [validators.Length(min=1, max=200)])
    # 作者
    author = StringField('Author', [validators.Length(min=1, max=100)])
    # 借阅状态
    state = StringField('State', [validators.Length(min=1, max=50)])
    # 用户借阅信息
    state_user = StringField('State_user', [validators.Length(min=1, max=200)])

class RegisterForm(Form):
    username = StringField('Username', [validators.Length(min=4, max=25)])
    password = PasswordField('Password', [
        validators.DataRequired(),
        validators.EqualTo('confirm', message='Passwords do not match')
    ])
    confirm = PasswordField('Confirm Password')
    phone = StringField('Phone',[validators.Length(11)])


class LoginForm(Form):
    username = StringField('Username', [validators.DataRequired()])
    password = PasswordField('Password', [validators.DataRequired()])
    admin = StringField('Admin', [validators.DataRequired()])

#运行项目时同时运行本地的gpt服务
def run_gpt_service():
    # 获取 app.py 文件所在的目录
    base_dir = os.path.dirname(os.path.abspath(__file__))

    # 构建 gpt 文件夹的路径
    gpt_folder = os.path.join(base_dir, 'gpt')

    # 使用 subprocess 模块在 gpt 文件夹中运行 "node app.mjs"
    subprocess.Popen(['cmd', '/c', 'node app.mjs'], cwd=gpt_folder)

#主页
@app.route('/', methods=['GET','POST'])
def main_index():

    return render_template('main_index.html')

# 登录路由
@app.route('/login', methods=['GET', 'POST'])
def login():
    message = ''
    if request.method == 'POST':
        #获取前端发送的数据
        form = LoginForm(request.form)
        username = form.username.data
        password_candidate = form.password.data
        # 从数据库获取用户数据
        cur = mysql.connection.cursor()
        # 普通用户数据
        result_user = cur.execute('SELECT * FROM users WHERE username = %s', [username])
        #检查用户是否注册
        if result_user == 0:
            message = '未注册用户'
        elif result_user > 0:
            data = cur.fetchone()
            password = data['password']
            # 验证密码
            if password_candidate == password:
                user = User(data['id'], data['username'], is_admin=False)
                login_user(user)
                # 验证成功后进行页面的跳转
                return redirect(url_for('admin'))
            else:
                message = '用户登录失败请重新登录'
        result_admin = cur.execute('SELECT * FROM administrator WHERE username = %s', [username])
        if result_admin>0:
            data = cur.fetchone()
            password = data['password']
            # 验证密码
            if password_candidate == password:
                user = User(data['id'], data['username'], is_admin=True)
                login_user(user)
                # 验证成功后进行页面的跳转
                return redirect(url_for('admin'))
            else:
                message = '管理员登录失败请重新登录'
        cur.close()
        return render_template('login.html', form=form, message=message)
    return render_template('login.html', message=message)

# 注册路由
@app.route('/register', methods=['GET', 'POST'])
def register():
    message = '请注册'
    if request.method == 'POST':
        form = RegisterForm(request.form)
    else:
        form = RegisterForm()
    if request.method == 'POST':
        username = form.username.data
        password = form.password.data
        confirm = form.confirm.data
        phone = form.phone.data
        cur = mysql.connection.cursor()
        #判断用户名是否已经注册
        result = cur.execute('SELECT * FROM users WHERE username=%s',[username])
        if result!=0:
            message = '用户名已存在请重新注册'
            return render_template('register.html', form=form, message=message)
        #确认密码
        if password == confirm:
            # 将用户数据插入到数据库
            cur.execute('INSERT INTO users(username, password ,phone) VALUES(%s, %s, %s)', (username, password, phone))
            mysql.connection.commit()
            cur.close()

            # flash('You are now registered and can log in', 'success')
            return redirect(url_for('login'))
        message = '注册失败请确认你的密码'
    return render_template('register.html', form=form, message = message)

# 检查是否是管理员
@app.route('/admin')
# 登录验证
@login_required
def admin():
    print(current_user.is_admin)
    if not current_user.is_admin:
        # 如果不是管理员就实现路由重定向跳转到用户的页面
        return redirect(url_for('index_user',value=0))
    # 如果当前用户是管理员，则显示管理员页面

    return redirect(url_for('index'))

# 注销路由
@app.route('/logout')
# 确保用户已登录才能使用系统功能
@login_required
def logout():
    # 注销用户
    logout_user()
    message = ''
    return redirect(url_for('login',message=message))

# 检测数据库是否连接成功
@app.route('/check_db_connection')
def check_db_connection():
    try:
        cur = mysql.connection.cursor()
        cur.execute('SELECT 1')
        result = cur.fetchone()
        if result:
            return "数据库连接成功！"
        else:
            return "数据库连接失败！"
    except Exception as e:
        return f"数据库连接出错：{str(e)}"

# 查找图书路由
@app.route('/search', methods=['GET', 'POST'])
# 登录验证
@login_required
def search_book():
    if request.method == 'POST':
        book_name = request.form['book_name']
        cur = mysql.connection.cursor()
        cur.execute('SELECT * FROM books WHERE title = %s', [book_name])
        book = cur.fetchone()
        cur.close()
        if book:
            if not current_user.is_admin:
                username = request.args['username']
                value = request.args['value']
                return render_template('search_book_user.html', book=book,username=username,value=value)
            else:
                return render_template('search_book.html', book=book)
        else:
            message = '无该书籍信息请查找其他书籍'
            if not current_user.is_admin:
                username = request.args['username']
                value = request.args['value']
                return redirect(url_for('index_user',message = message,username=username,value=value))
            else:
                return redirect(url_for('index2',message = message))

# 用户主页路由
@app.route('/index_user')
# 登录验证
@login_required
def index_user():
    print(request.args)
    value_str = request.args.get('amp;value')
    if value_str is None:
        value = -1
    else:
        value = int(value_str)

    value_1_str = request.args.get('value')
    if value_1_str is None:
        value_1 = -1
    else:
        value_1 = int(value_1_str)

    message = ''
    page_num = request.args.get('page_num', 1, type=int)
    per_page = 10
    cur = mysql.connection.cursor()
    cur.execute('SELECT * FROM books    LIMIT %s OFFSET %s', (per_page, (page_num - 1) * per_page))
    books = cur.fetchall()
    cur.execute('SELECT COUNT(*) as total FROM books')
    total = cur.fetchone()['total']
    cur.close()
    if value == 1 :
        username = request.args.get('username')
    elif value_1 == 1:
        username = request.args.get('username')
        value = value_1
    else:
        username = current_user.username
    print(username,value)
    return render_template('index_user.html', books=books, username = username, page_num=page_num,
                           total=total, per_page=per_page,message=message,value=value)

# 借阅功能
@app.route('/user_state/<string:id>', methods=['POST'])
# 登录验证
@login_required
def user_state(id):
    print(request.args)
    value_str = request.args.get('amp;value')
    if value_str is None:
        value = -1
    else:
        value = int(value_str)

    value_1_str = request.args.get('value')
    if value_1_str is None:
        value_1 = -1
    else:
        value_1 = int(value_1_str)
    if value == 1 :
        username = request.args.get('username')
    elif value_1 == 1:
        username = request.args.get('username')
        value = value_1
    else:
        username = current_user.username
    print(username,value)

    cur = mysql.connection.cursor()
    cur.execute('SELECT * FROM users WHERE username = %s',[current_user.username])
    user = cur.fetchall()
    print(user)
    phone = user[0]['phone']
    print(phone)
    state_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    #更新数据库内容
    cur.execute('UPDATE books SET state = %s ,state_user = %s ,user_phone = %s ,state_time = %s WHERE id=%s', ('已借阅', username,phone ,state_time ,id))
    mysql.connection.commit()
    cur.close()
    page_num = (int(id)-1)//10+1
    return redirect(url_for('index_user',page_num = page_num,value=value,username = username))

# 用户查看个人借阅图书信息归还功能使用查看路由
@app.route('/user_return_book', methods=['GET', 'POST'])
@login_required
def user_return_book():
    username = request.args.get('username')
    value = request.args.get('value')
    page_num = request.args.get('page_num', 1, type=int)
    per_page = 10
    cur = mysql.connection.cursor()
    cur.execute('SELECT * FROM books WHERE state_user = %s LIMIT %s OFFSET %s',
                (username, per_page, (page_num - 1) * per_page))
    books = cur.fetchall()
    #获取图书的总数
    cur.execute('SELECT COUNT(*) as total FROM books WHERE state_user =%s',[username])
    total = cur.fetchone()['total']
    cur.close()

    return render_template('user_book_state.html', books=books, username=username, page_num=page_num,
                           total=total, per_page=per_page,value=value)

# 用户归还图书路由
@app.route('/return_book/<string:id>', methods=['POST'])
# 登录验证
@login_required
def return_book(id):
    username = request.args.get('username')
    value = request.args.get('value')
    cur = mysql.connection.cursor()
    cur.execute('UPDATE books SET state = %s,state_user =%s ,user_phone = %s,state_time = %s WHERE id=%s', ('未借阅', '无',None,None, id))
    mysql.connection.commit()
    cur.close()
    return redirect(url_for('user_return_book',username=username,value=value))

# 用户借阅分页路由
@app.route('/page_user_state/<int:page_num>')
# 登录验证
@login_required
def page_user_state(page_num):
    value = request.args.get('value')
    username = request.args.get('username')
    per_page = 10
    cur = mysql.connection.cursor()
    cur.execute('SELECT * FROM books WHERE state_user =%s LIMIT %s OFFSET %s', (username,per_page, (page_num - 1) * per_page))
    books = cur.fetchall()
    # 获取图书的总数
    cur.execute('SELECT COUNT(*) as total FROM books WHERE state_user =%s',[username])
    total = cur.fetchone()['total']
    cur.close()
    return render_template('user_book_state.html', books=books, username=username, page_num=page_num,
                           total=total, per_page=per_page,value=value)


#管理员图片展示页面
@app.route('/ind')
def ind():
   return render_template('in.html')

#管理主页路由
@app.route('/index')
@login_required
def index():
    username = current_user.username
    return render_template('index.html',username =username)

# 管理员主页路由
@app.route('/index2')
# 登录验证
@login_required
def index2():
    message = ''
    page_num = request.args.get('page_num', 1, type=int)
    per_page = 10
    cur = mysql.connection.cursor()
    cur.execute('SELECT * FROM books LIMIT %s OFFSET %s', (per_page, (page_num - 1) * per_page))
    books = cur.fetchall()
    cur.execute('SELECT COUNT(*) as total FROM books')
    total = cur.fetchone()['total']
    cur.close()
    print(message)
    return render_template('index2.html', books=books, page_num=page_num, total=total,
                           per_page=per_page,message = message)

#批量插入图书数量
@app.route('/addnumer',methods=['GET', 'POST'])
# 登录验证
@login_required
def addnumer():
    booknum = int(request.form['number'])
    session['booknum'] = booknum
    return render_template('add_book.html',booknum=booknum)

# 添加图书路由
@app.route('/add', methods=['GET', 'POST'])
# 登录验证
@login_required
def add_book():
    if request.method == 'GET':
        session['booknum'] = 0
    booknum = session.get('booknum', 0)
    titleList = request.form.getlist('title')
    authorList = request.form.getlist('author')
    img_urlList = request.form.getlist('img_url')
    book_img_messageList = request.form.getlist('book_img_message')

    message = '插入成功'
    for i in range(booknum):
        if request.method == 'POST':
            title = titleList[i]
            author = authorList[i]
            img_url = img_urlList[i]
            book_img_message = book_img_messageList[i]
            if title == '' and author == '':
                message = '书籍信息为空，请重新输入'
                return render_template('add_book.html', message=message, booknum=booknum)
            # 将图书数据插入到数据库
            cur = mysql.connection.cursor()
            #判断已有书籍
            result = cur.execute('SELECT * FROM books WHERE title=%s',[title])
            if result == 0 and title!='' and author != '':
                #计算图书数量添加id
                cur.execute('SELECT COUNT(*) as total FROM books')
                total = cur.fetchone()['total']
                id = total +2
                cur.execute('INSERT INTO books(id,title, author,state,state_user,user_phone,state_time,img_url,book_img_message)'
                            ' VALUES(%s,%s, %s, %s,%s,%s,%s,%s,%s)', (id,title, author,'未借阅','无',None,None,img_url,book_img_message))
                mysql.connection.commit()
                cur.close()
            else:
                message = '书籍已存在,请重新输入'
                return render_template('add_book.html', message=message, booknum=booknum)
    return render_template('add_book.html',message=message,booknum=booknum)

# 编辑图书路由
@app.route('/edit/<string:id>', methods=['GET', 'POST'])
# 登录验证
@login_required
def edit_book(id):
    cur = mysql.connection.cursor()
    cur.execute('SELECT * FROM books WHERE id = %s', [int(id)])
    book = cur.fetchone()

    #实例化图书类
    form = BookForm(request.form)
    #存入数据库获取到的数据到图书类中
    form.title.data = book['title']
    form.author.data = book['author']
    form.state.data = book['state']

    if request.method == 'POST':
        title = request.form['title']
        author = request.form['author']
        state = request.form['state']
        if state == '未借阅':
            # 更新数据库中的图书数据
            cur = mysql.connection.cursor()
            cur.execute('UPDATE books SET title=%s, author=%s ,state=%s ,state_user=%s,user_phone = %s,state_time = %s WHERE id=%s',
                        (title, author, state, '无', None, None, id))
            mysql.connection.commit()
        return redirect(url_for('index2'))

    return render_template('edit_book.html', form=form, book=book)

# 删除图书路由
@app.route('/delete/<string:id>', methods=['POST'])
# 登录验证
@login_required
def delete_book(id):
    cur = mysql.connection.cursor()
    cur.execute('DELETE FROM books WHERE id = %s', [id])
    mysql.connection.commit()
    cur.close()
    return redirect(url_for('index2'))

#管理查阅用户功能
@app.route('/search_user', methods=['GET', 'POST'])
@login_required
def search_user():
    #获取图书的总数
    if request.method == 'POST':
        username = request.form['user_name']
        page_num = request.args.get('page_num', 1, type=int)
        per_page = 10
        cur = mysql.connection.cursor()
        result = cur.execute('SELECT * FROM books WHERE state_user = %s LIMIT %s OFFSET %s',
                    (username, per_page, (page_num - 1) * per_page))
        books = cur.fetchall()
        cur.execute('SELECT COUNT(*) as total FROM books WHERE state_user =%s',[username])
        total = cur.fetchone()['total']
        cur.close()
        if result <=0:
            return redirect(url_for('index2'))
        return render_template('search_user.html', books=books, page_num=page_num,
                               total=total, per_page=per_page,username = username)

# 管理查阅用户分页路由
@app.route('/page_admin_state/<int:page_num>')
# 登录验证
@login_required
def page_admin_state(page_num):
    print(request.args)
    username = request.args.get('username')
    print(username)
    per_page = 10
    cur = mysql.connection.cursor()
    cur.execute('SELECT * FROM books WHERE state_user =%s LIMIT %s OFFSET %s', (username,per_page, (page_num - 1) * per_page))
    books = cur.fetchall()
    # 获取图书的总数
    cur.execute('SELECT COUNT(*) as total FROM books WHERE state_user =%s',[username])
    total = cur.fetchone()['total']
    cur.close()
    return render_template('search_user.html', books=books, page_num=page_num,
                           total=total, per_page=per_page,username = username)

#人脸登录路由
@app.route('/face_login', methods=['GET', 'POST'])
def face_login():
    if request.method == 'POST':
        username = request.form['userName']
        userImgSrc = request.form['userImgSrc']
        #判断用户名是否录入了信息
        filename = []
        for filenames in os.walk('./image/Register'):
            filename = filenames[2]
        if username+'.png' in filename:
            # 转换base64编码为图像并保存
            img_data = base64.b64decode(userImgSrc.split(',', 1)[-1])
            img_path = os.path.join("image/Login", f"faceNow.png")
            with open(img_path, 'wb') as f:
                f.write(img_data)

            register_path = 'image/Register/'+username+'.png'
            login_path = img_path
            #接口调用比结果
            score = face_compare_python3_demo.run('1ce99afc','2e4249f6d20062d02f8e75f2f9c9dada','ZDA0M2JhOWJmYzEzOTVmZWZlNTZhYjFh'
                                          ,register_path,login_path)
            score = float(score)
            if score>0.67:
                session['logged_in'] = True
                session['username'] = username
                return jsonify({"result": "1"})  # 人脸识别成功
            else:
                return jsonify({"result": "-1"})  # 人脸识别失败
        return jsonify({"result": "0"}) #用户未注册
    return render_template("faceLogin.html")



#人脸注册路由
@app.route('/face_register', methods=['GET', 'POST'])
def face_register():
    if request.method == 'POST':
        username = request.form['userName']
        userImgSrc = request.form['userImgSrc']
        #判断用户是否注册
        cur = mysql.connection.cursor()
        result = cur.execute('SELECT * FROM users WHERE username = %s', [username])
        print(result)
        if result == 0:
            return jsonify({"result": "3"})
        # 转换base64编码为图像并保存
        img_data = base64.b64decode(userImgSrc.split(',', 1)[-1])
        filename = []
        for filenames in os.walk('./image/Register'):
            filename = filenames[2]
        #检查是否存在该用户的照片
        if f"{username}.png" in filename:
            return jsonify({"result": "2"})  # 用户已存在
        img_path = os.path.join("image/Register", f"{username}.png") #格式化字符串
        with open(img_path, 'wb') as f:
            f.write(img_data)

        #检测照片文件是否传入判断人脸注册是否成功
        for filenames in os.walk('./image/Register'):
            filename = filenames[2]

        if f"{username}.png" in filename:
            return jsonify({"result": "1"})  # 人脸录入成功
        else:
            return jsonify({"result": "0"})  # 人脸录入失败
    return render_template("faceRegister.html")

if __name__ == '__main__':
    # 启动 Flask 应用程序 debug=True 启用调试模式
    # 启用调试模式后，应用程序还会自动重新加载，这意味着您可以在不重新启动应用程序的情况下进行更改并立即查看它们的效果。
    run_gpt_service()
    app.run(debug=True,port=8080)
